import { IRawMsg } from "@/chatlog_types/IRawMsg";
import { Chat } from "@/views/Chat";
import localforage from "localforage";
import { ISessionItem } from "../session";
import { tasks_keeper } from "../tasks/instance";
import { BaseChatMgr } from "./BaseChatMgr";
import { LocalMessageLoader } from "./LocalMessageLoader";
import { create_msg_commit_job } from "./create_msg_commit_job";


export class GhostChatMgr extends BaseChatMgr {
  static readonly TAG: string = 'GhostChatMgr';
  readonly TAG: string = GhostChatMgr.TAG;
  readonly loader: LocalMessageLoader = new LocalMessageLoader(this, 1000)
  protected _messages_length = 0;
  protected _latest: Chat.Message<IRawMsg> | undefined
  protected _earliest: Chat.Message<IRawMsg> | undefined
  protected _mark_as_new: boolean = false;
  protected _is_history_done: boolean = false;
  override get messages_length(): number {
    return this._messages_length;
  }
  override get messages(): Chat.Message<IRawMsg>[] {
    throw new Error(`[${this.TAG}]get messages() is not supported`)
  }
  override get latest(): Chat.Message<IRawMsg> | undefined {
    return this._latest;
  }
  override get earliest(): Chat.Message<IRawMsg> | undefined {
    return this._earliest;
  }
  constructor(session: ISessionItem) {
    super(session)
    this.poller.interval = 10000;
    this.callbacks.add({
      on_msgs_added: this.on_msgs_added
    })
  }
  stop() {
    // console.log(`[${this.TAG}::stop] ${this.session.userName}`)
    this.poller.stop()
  }
  start() {
    this._mark_as_new = true;
    this.poller.start();
  }
  on_history_done() {
    this._is_history_done = true;
  }
  protected override async poll(): Promise<void> {
    if (this._mark_as_new)
      this.load_news()
    else if (!this._is_history_done)
      this.load_history();
    else this.stop()
    if (this._mark_as_new) this._mark_as_new = false
  }

  override clear_msgs() {
    this._latest = void 0;
    this._earliest = void 0;
    this._messages_length = 0;
  }

  override append_msgs(msgs: Chat.Message<IRawMsg>[]) {
    if (msgs.length) this._latest = msgs[msgs.length - 1]
    if (!this._messages_length) this._earliest = msgs[0]
    this._messages_length += msgs.length
  }

  override insert_msgs(index: number, msgs: Chat.Message<IRawMsg>[]) {
    this._messages_length += msgs.length
    if (index >= this._messages_length) this._latest = msgs[msgs.length - 1]
    if (index <= 0) this._earliest = msgs[0]
  }
  override set_msgs(msgs: Chat.Message<IRawMsg>[]) {
    this._messages_length = msgs.length;
    this._latest = msgs[msgs.length - 1];
    this._earliest = msgs[0]
  }
  on_msgs_added(mgr: GhostChatMgr, msgs: Chat.Message<IRawMsg>[]) {
    for (const msg of msgs) {
      const { raw } = msg;
      if (!raw) continue;
      need_update(raw).then((n) => n && tasks_keeper().push(create_msg_commit_job(raw, n === 'thumb')))
    }
  }
}
export const ghost_messages_forage = localforage.createInstance({ name: 'ghost_messages_forage' })
export const job_key = (raw: IRawMsg) => {
  return `msg##${raw.account}##${raw.talker}##${raw.seq}`
}
async function need_update(raw: IRawMsg): Promise<boolean | 'thumb'> {
  const key = job_key(raw);
  return ghost_messages_forage.getItem<boolean | 'thumb'>(key).then(v => {
    if (!v || v === 'thumb') return true;
    if (typeof v === 'boolean') return !v;
    return true;
  })
}

